namespace SimpleWebServices.Data
{
    using System;
    using System.Collections;
    using System.Text;
    using System.Xml;
    using SimpleWebServices.Security.Cryptography;

    public sealed class Entity
    {
        public Entity()
            : this(null as string)
        {
        }

        public Entity(string value)
        {
            this.Buffer = new StringBuilder();
            this.Append(value);
        }

        private StringBuilder Buffer
        {
            get;
            set;
        }

        private int Tabs
        {
            get;
            set;
        }

        public static implicit operator string(Entity obj)
        {
            return (null == obj) ? null as string : obj.ToString();
        }

        public void Append(bool value)
        {
            if (value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(byte value)
        {
            if (byte.MinValue != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(char value)
        {
            if (char.MinValue != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(DateTime value)
        {
            if (DateTime.MinValue != value)
            {
                this.Append(value.ToXmlString());
            }
        }

        public void Append(DateTimeOffset value)
        {
            if (DateTimeOffset.MinValue != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(decimal value)
        {
            if (0 != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(double value)
        {
            if (0 != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(float value)
        {
            if (0 != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(Guid value)
        {
            if (Guid.Empty != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(int value)
        {
            if (0 != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(long value)
        {
            if (0 != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(short value)
        {
            if (0 != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(string value)
        {
            if (null != value)
            {
                if (0 != this.Buffer.Length)
                {
                    this.Buffer.Append(Environment.NewLine);
                }

                for (int i = 0; i < this.Tabs; i++)
                {
                    this.Buffer.Append("\t");
                }

                this.Buffer.Append(value);
            }
        }

        public void Append(TimeSpan value)
        {
            if (TimeSpan.MinValue != value)
            {
                this.Append(XmlConvert.ToString(value));
            }
        }

        public void Append(IRecord value)
        {
            if (null != value)
            {
                string entity = value.Entity;
                if (!string.IsNullOrEmpty(entity))
                {
                    this.Append(MD5Hash.Compute(entity));
                }
            }
        }

        public void Append(object value)
        {
            if (null == value)
            {
            }
            else
            {
                IEnumerable enumerable = value as IEnumerable;
                if (null == enumerable)
                {
                    string temp = value.ToString();
                    if (!string.IsNullOrEmpty(temp))
                    {
                        this.Append(MD5Hash.Compute(temp));
                    }
                }
                else
                {
                    this.Append(enumerable);
                }
            }
        }

        public void Indent()
        {
            this.Tabs++;
        }

        public void Unindent()
        {
            if (0 == this.Tabs)
            {
                throw new InvalidOperationException("This instance is not indented.");
            }

            this.Tabs--;
        }

        public override string ToString()
        {
            return this.Buffer.ToString();
        }

        private void Append(IEnumerable value)
        {
            if (null != value)
            {
                StringBuilder buffer = new StringBuilder();
                foreach (var item in value)
                {
                    buffer.Append(null == item ? null as string : item.ToString());
                }

                if (0 != buffer.Length)
                {
                    this.Append(MD5Hash.Compute(buffer.ToString()));
                }
            }
        }
    }
}